#include "jassvmhooks.h"
#include "Extern_global_Variable.h"

#include "wc3observer.h"

TInstanceHandle __stdcall hook_RegisterInstance()
{
	TInstanceHandle Result;
	Result = orig_RegisterInstance();
	pOnInstanceCreated(Result);
	return Result;
};

procedure __stdcall hook_FreeInstance()	// fastcall
{
	TInstanceHandle hInstance;

	__asm
	{
		mov hInstance, ecx
	};

	pOnInstanceDestroying(hInstance);

	__asm
	{
		mov ecx, hInstance 
	};
	orig_FreeInstance();
};

TScriptExitCode __stdcall hook_Instance_ExecuteFunctionWithOptionalInit(PChar FunctionName, PDword ScriptResult, LongBool InitGlobals, Dword OpLimit, Dword Unused) // thiscall
{
	PInstance _this;

	__asm
	{
		mov _this, ecx 
	};

	if (InitGlobals)
	{
		pOnInstanceInit(_this->Handle);
	};

	return pOnExecuteFunctionByName(_this->Handle, FunctionName, ScriptResult);
};

TScriptExitCode __stdcall hook_ExecuteFunctionByHandle(Pointer Parameters, PDword ScriptResult, Dword OpLimit, Dword Unused, LongBool ForceNewRun) // fastcall
{
	TInstanceHandle hInstance;
	Dword hFunction;

	__asm
	{
		mov hInstance, ecx
		mov hFunction, edx
	};

	return pOnExecuteFunctionByHandle(hInstance, hFunction, ScriptResult);
};

TJassStringHandle __stdcall hook_Instance_GetStringHandle(PChar Value) // thiscall
{
	PInstance _this;

	__asm
	{
		mov _this, ecx 
	};
	return pOnInstanceGetStringHandle(_this->Handle, Value);
};

LongBool __stdcall hook_CGameState_ConnectToVarChangeEvent(PChar variable_name, Dword event_id, PObserver handler) // thiscall
{
	LongBool Result;
	Result = orig_CGameState_ConnectToVarChangeEvent(variable_name, event_id, handler);
	pOnEnableVarChangeEvent(variable_name);
	return Result;
};

procedure jassvmhooks_Init()
{
	Hook(Pointer(_RegisterInstance), &hook_RegisterInstance, (Pointer)&orig_RegisterInstance,NULL);
	Hook(Pointer(_FreeInstance), &hook_FreeInstance, (Pointer)(&orig_FreeInstance),NULL);
	Hook(Pointer(_Instance_ExecuteFunctionWithOptionalInit), &hook_Instance_ExecuteFunctionWithOptionalInit, (Pointer)(&orig_Instance_ExecuteFunctionWithOptionalInit),NULL);
	Hook(Pointer(_ExecuteFunctionByHandle), &hook_ExecuteFunctionByHandle, (Pointer)(&orig_ExecuteFunctionByHandle),NULL);
	Hook(Pointer(_Instance_GetStringHandle), &hook_Instance_GetStringHandle, (Pointer)(&orig_Instance_GetStringHandle),NULL);
	Hook(Pointer((HMODULE)GameDll + 0x4312D0), &hook_CGameState_ConnectToVarChangeEvent, (Pointer)(&orig_CGameState_ConnectToVarChangeEvent),NULL);
};

void jassvmhooks_main()
{
	wc3main_SubscribeOnInitDone(&jassvmhooks_Init);
}
